/*  Copyright (c) 2012 William Rogers and James Boud

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

using System;
using SlimDX;
using SlimDX.Direct3D11;

namespace JBBRXG11
{
    // This is a place to put the many enum type conversions
    // required.  Gradually I should try to move them all to
    // here, but several are already in RenderState and they
    // can stay there for the meanwhile.

    public enum PrimitiveType
    {
        PointList = 1,
        LineList = 2,
        LineStrip = 3,
        TriangleList = 4,
        TriangleStrip = 5,
        TriangleFan = 6,
        // Code assumes adjacency types all come after non adjacency types
        // and that LineListWithAdjacency is the first adjacency type
        // See const declaration following.
        LineListWithAdjacency = 7,
        LineStripWithAdjacency = 8,
        TriangleListWithAdjacency = 9,
        TriangleStripWithAdjacency = 10,

        PatchListWith1ControlPoint = 11,
        PatchListWith2ControlPoints = 12,
        PatchListWith3ControlPoints = 13,
        PatchListWith4ControlPoints = 14,
        PatchListWith5ControlPoints = 15,
        PatchListWith6ControlPoints = 16,
        PatchListWith7ControlPoints = 17,
        PatchListWith8ControlPoints = 18,
        PatchListWith9ControlPoints = 19,

        PatchListWith10ControlPoints = 20,
        PatchListWith11ControlPoints = 21,
        PatchListWith12ControlPoints = 22,
        PatchListWith13ControlPoints = 23,
        PatchListWith14ControlPoints = 24,
        PatchListWith15ControlPoints = 25,
        PatchListWith16ControlPoints = 26,
        PatchListWith17ControlPoints = 27,
        PatchListWith18ControlPoints = 28,
        PatchListWith19ControlPoints = 29,

        PatchListWith20ControlPoints = 30,
        PatchListWith21ControlPoints = 31,
        PatchListWith22ControlPoints = 32,
        PatchListWith23ControlPoints = 33,
        PatchListWith24ControlPoints = 34,
        PatchListWith25ControlPoints = 35,
        PatchListWith26ControlPoints = 36,
        PatchListWith27ControlPoints = 37,
        PatchListWith28ControlPoints = 38,
        PatchListWith29ControlPoints = 39,

        PatchListWith30ControlPoints = 40,
        PatchListWith31ControlPoints = 41,
        PatchListWith32ControlPoints = 42
    }

    public class EnumConversions
    {
        const PrimitiveType FirstAdjacencyType = PrimitiveType.LineListWithAdjacency;

        internal static SlimDX.DXGI.Format convert(Microsoft.Xna.Framework.Graphics.SurfaceFormat sform)
        {
            if (sform == Microsoft.Xna.Framework.Graphics.SurfaceFormat.Color)
                return SlimDX.DXGI.Format.R8G8B8A8_UNorm;
            else if (sform == Microsoft.Xna.Framework.Graphics.SurfaceFormat.Single)
                return SlimDX.DXGI.Format.D32_Float;
            else throw new Exception("JBBRXG11: NYI - can't handle buffer surface format");
        }

        internal static SlimDX.DXGI.Format convert(Microsoft.Xna.Framework.Graphics.DepthFormat dform)
        {
            if (dform == Microsoft.Xna.Framework.Graphics.DepthFormat.Depth24)
                return SlimDX.DXGI.Format.D32_Float;
            else if (dform == Microsoft.Xna.Framework.Graphics.DepthFormat.Depth16)
                return SlimDX.DXGI.Format.D16_UNorm;//TODO: This was D32. Why?
            else if (dform == Microsoft.Xna.Framework.Graphics.DepthFormat.Depth24Stencil8)
                return SlimDX.DXGI.Format.D24_UNorm_S8_UInt;
            else throw new Exception("JBBRXG11: NYI - can't handle buffer format");
        }

        //TODO: color conversion.

        internal static PrimitiveTopology convert(PrimitiveType prim)
        {
            PrimitiveTopology topo = PrimitiveTopology.LineList;
            switch (prim)
            {
                case PrimitiveType.LineList:
                    topo = PrimitiveTopology.LineList;
                    break;
                case PrimitiveType.LineStrip:
                    topo = PrimitiveTopology.LineStrip;
                    break;
                case PrimitiveType.PointList:
                    topo = PrimitiveTopology.PointList;
                    break;
                case PrimitiveType.TriangleFan:
                    throw new Exception("Sorry, DX11 does not support TriangleFan topology");
                case PrimitiveType.TriangleList:
                    topo = PrimitiveTopology.TriangleList;
                    break;
                case PrimitiveType.TriangleStrip:
                    topo = PrimitiveTopology.TriangleStrip;
                    break;
                case PrimitiveType.LineListWithAdjacency:
                    topo = PrimitiveTopology.LineListWithAdjacency;
                    break;
                case PrimitiveType.LineStripWithAdjacency:
                    topo = PrimitiveTopology.LineStripWithAdjacency;
                    break;
                case PrimitiveType.TriangleListWithAdjacency:
                    topo = PrimitiveTopology.TriangleListWithAdjacency;
                    break;
                case PrimitiveType.TriangleStripWithAdjacency:
                    topo = PrimitiveTopology.TriangleStripWithAdjacency;
                    break;



                case PrimitiveType.PatchListWith1ControlPoint:
                    topo = PrimitiveTopology.PatchListWith1ControlPoint;
                    break;
                case PrimitiveType.PatchListWith2ControlPoints:
                    topo = PrimitiveTopology.PatchListWith2ControlPoints;
                    break;
                case PrimitiveType.PatchListWith3ControlPoints:
                    topo = PrimitiveTopology.PatchListWith3ControlPoints;
                    break;
                case PrimitiveType.PatchListWith4ControlPoints:
                    topo = PrimitiveTopology.PatchListWith4ControlPoints;
                    break;
                case PrimitiveType.PatchListWith5ControlPoints:
                    topo = PrimitiveTopology.PatchListWith5ControlPoints;
                    break;
                case PrimitiveType.PatchListWith6ControlPoints:
                    topo = PrimitiveTopology.PatchListWith6ControlPoints;
                    break;
                case PrimitiveType.PatchListWith7ControlPoints:
                    topo = PrimitiveTopology.PatchListWith7ControlPoints;
                    break;
                case PrimitiveType.PatchListWith8ControlPoints:
                    topo = PrimitiveTopology.PatchListWith8ControlPoints;
                    break;
                case PrimitiveType.PatchListWith9ControlPoints:
                    topo = PrimitiveTopology.PatchListWith9ControlPoints;
                    break;


                case PrimitiveType.PatchListWith10ControlPoints:
                    topo = PrimitiveTopology.PatchListWith10ControlPoints;
                    break;
                case PrimitiveType.PatchListWith11ControlPoints:
                    topo = PrimitiveTopology.PatchListWith11ControlPoints;
                    break;
                case PrimitiveType.PatchListWith12ControlPoints:
                    topo = PrimitiveTopology.PatchListWith12ControlPoints;
                    break;
                case PrimitiveType.PatchListWith13ControlPoints:
                    topo = PrimitiveTopology.PatchListWith13ControlPoints;
                    break;
                case PrimitiveType.PatchListWith14ControlPoints:
                    topo = PrimitiveTopology.PatchListWith14ControlPoints;
                    break;
                case PrimitiveType.PatchListWith15ControlPoints:
                    topo = PrimitiveTopology.PatchListWith15ControlPoints;
                    break;
                case PrimitiveType.PatchListWith16ControlPoints:
                    topo = PrimitiveTopology.PatchListWith16ControlPoints;
                    break;
                case PrimitiveType.PatchListWith17ControlPoints:
                    topo = PrimitiveTopology.PatchListWith17ControlPoints;
                    break;
                case PrimitiveType.PatchListWith18ControlPoints:
                    topo = PrimitiveTopology.PatchListWith18ControlPoints;
                    break;
                case PrimitiveType.PatchListWith19ControlPoints:
                    topo = PrimitiveTopology.PatchListWith19ControlPoints;
                    break;
                case PrimitiveType.PatchListWith20ControlPoints:
                    topo = PrimitiveTopology.PatchListWith20ControlPoints;
                    break;

                case PrimitiveType.PatchListWith21ControlPoints:
                    topo = PrimitiveTopology.PatchListWith21ControlPoints;
                    break;
                case PrimitiveType.PatchListWith22ControlPoints:
                    topo = PrimitiveTopology.PatchListWith22ControlPoints;
                    break;
                case PrimitiveType.PatchListWith23ControlPoints:
                    topo = PrimitiveTopology.PatchListWith23ControlPoints;
                    break;
                case PrimitiveType.PatchListWith24ControlPoints:
                    topo = PrimitiveTopology.PatchListWith24ControlPoints;
                    break;
                case PrimitiveType.PatchListWith25ControlPoints:
                    topo = PrimitiveTopology.PatchListWith25ControlPoints;
                    break;
                case PrimitiveType.PatchListWith26ControlPoints:
                    topo = PrimitiveTopology.PatchListWith26ControlPoints;
                    break;
                case PrimitiveType.PatchListWith27ControlPoints:
                    topo = PrimitiveTopology.PatchListWith27ControlPoints;
                    break;
                case PrimitiveType.PatchListWith28ControlPoints:
                    topo = PrimitiveTopology.PatchListWith28ControlPoints;
                    break;
                case PrimitiveType.PatchListWith29ControlPoints:
                    topo = PrimitiveTopology.PatchListWith29ControlPoints;
                    break;
                case PrimitiveType.PatchListWith30ControlPoints:
                    topo = PrimitiveTopology.PatchListWith30ControlPoints;
                    break;

                case PrimitiveType.PatchListWith31ControlPoints:
                    topo = PrimitiveTopology.PatchListWith31ControlPoints;
                    break;
                case PrimitiveType.PatchListWith32ControlPoints:
                    topo = PrimitiveTopology.PatchListWith32ControlPoints;
                    break;
            }
            return topo;
        }

        internal static SlimDX.Direct3D11.TextureAddressMode convert(Microsoft.Xna.Framework.Graphics.TextureAddressMode tam)
        {
            switch (tam)
            {
                case Microsoft.Xna.Framework.Graphics.TextureAddressMode.Clamp:
                    return SlimDX.Direct3D11.TextureAddressMode.Clamp;
                case Microsoft.Xna.Framework.Graphics.TextureAddressMode.Mirror:
                    return SlimDX.Direct3D11.TextureAddressMode.Mirror;
                case Microsoft.Xna.Framework.Graphics.TextureAddressMode.Wrap:
                    return SlimDX.Direct3D11.TextureAddressMode.Wrap;
            }
            return SlimDX.Direct3D11.TextureAddressMode.Clamp;
        }

        internal static Microsoft.Xna.Framework.Graphics.TextureAddressMode convert(SlimDX.Direct3D11.TextureAddressMode dxtam)
        {
            switch (dxtam)
            {
                case SlimDX.Direct3D11.TextureAddressMode.Border:
                    throw new Exception("XNA 4.0 does not support texture address mode 'Border' in this context");
                case SlimDX.Direct3D11.TextureAddressMode.Clamp:
                    return Microsoft.Xna.Framework.Graphics.TextureAddressMode.Clamp;
                case SlimDX.Direct3D11.TextureAddressMode.Mirror:
                    return Microsoft.Xna.Framework.Graphics.TextureAddressMode.Mirror;
                case SlimDX.Direct3D11.TextureAddressMode.MirrorOnce:
                    throw new Exception("XNA 4.0 does not support texture address mode 'MirrowOnce' in this context");
                case SlimDX.Direct3D11.TextureAddressMode.Wrap:
                    return Microsoft.Xna.Framework.Graphics.TextureAddressMode.Wrap;
            }
            return Microsoft.Xna.Framework.Graphics.TextureAddressMode.Clamp;
        }

        internal static SlimDX.Direct3D11.Filter convert(Microsoft.Xna.Framework.Graphics.TextureFilter tf)
        {
            switch (tf)
            {
                case Microsoft.Xna.Framework.Graphics.TextureFilter.Linear:
                    return SlimDX.Direct3D11.Filter.MinMagMipLinear;
                case Microsoft.Xna.Framework.Graphics.TextureFilter.Point:
                    return SlimDX.Direct3D11.Filter.MinMagMipPoint;
                case Microsoft.Xna.Framework.Graphics.TextureFilter.Anisotropic:
                    return SlimDX.Direct3D11.Filter.Anisotropic;
                case Microsoft.Xna.Framework.Graphics.TextureFilter.LinearMipPoint:
                    return SlimDX.Direct3D11.Filter.MinMagLinearMipPoint;
                case Microsoft.Xna.Framework.Graphics.TextureFilter.PointMipLinear:
                    return SlimDX.Direct3D11.Filter.MinMagPointMipLinear;
                case Microsoft.Xna.Framework.Graphics.TextureFilter.MinLinearMagPointMipLinear:
                    return SlimDX.Direct3D11.Filter.MinLinearMagPointMipLinear;
                case Microsoft.Xna.Framework.Graphics.TextureFilter.MinLinearMagPointMipPoint:
                    return SlimDX.Direct3D11.Filter.MinLinearMagMipPoint;
                case Microsoft.Xna.Framework.Graphics.TextureFilter.MinPointMagLinearMipLinear:
                    return SlimDX.Direct3D11.Filter.MinPointMagMipLinear;
                case Microsoft.Xna.Framework.Graphics.TextureFilter.MinPointMagLinearMipPoint:
                    return SlimDX.Direct3D11.Filter.MinPointMagLinearMipPoint;
            }
            return SlimDX.Direct3D11.Filter.ComparisonMinLinearMagMipPoint;
        }

        internal static Microsoft.Xna.Framework.Graphics.TextureFilter convert(SlimDX.Direct3D11.Filter dxtf)
        {
            switch (dxtf)
            {
                case SlimDX.Direct3D11.Filter.MinMagMipLinear:
                    return Microsoft.Xna.Framework.Graphics.TextureFilter.Linear;
                case SlimDX.Direct3D11.Filter.MinMagMipPoint:
                    return Microsoft.Xna.Framework.Graphics.TextureFilter.Point;
                case SlimDX.Direct3D11.Filter.Anisotropic:
                    return Microsoft.Xna.Framework.Graphics.TextureFilter.Anisotropic;
                case SlimDX.Direct3D11.Filter.MinMagLinearMipPoint:
                    return Microsoft.Xna.Framework.Graphics.TextureFilter.LinearMipPoint;
                case SlimDX.Direct3D11.Filter.MinMagPointMipLinear:
                    return Microsoft.Xna.Framework.Graphics.TextureFilter.PointMipLinear;
                case SlimDX.Direct3D11.Filter.MinLinearMagPointMipLinear:
                    return Microsoft.Xna.Framework.Graphics.TextureFilter.MinLinearMagPointMipLinear;
                case SlimDX.Direct3D11.Filter.MinLinearMagMipPoint:
                    return Microsoft.Xna.Framework.Graphics.TextureFilter.MinLinearMagPointMipPoint;
                case SlimDX.Direct3D11.Filter.MinPointMagMipLinear:
                    return Microsoft.Xna.Framework.Graphics.TextureFilter.MinPointMagLinearMipLinear;
                case SlimDX.Direct3D11.Filter.MinPointMagLinearMipPoint:
                    return Microsoft.Xna.Framework.Graphics.TextureFilter.MinPointMagLinearMipPoint;
            }
            throw new Exception("XNA 4 does not support comparison texture filters");
        }

        internal static Microsoft.Xna.Framework.Graphics.BlendFunction convert(BlendOperation op)
        {
            switch (op)
            {
                case BlendOperation.Add:
                    return Microsoft.Xna.Framework.Graphics.BlendFunction.Add;
                case BlendOperation.Maximum:
                    return Microsoft.Xna.Framework.Graphics.BlendFunction.Max;
                case BlendOperation.Minimum:
                    return Microsoft.Xna.Framework.Graphics.BlendFunction.Min;
                case BlendOperation.ReverseSubtract:
                    return Microsoft.Xna.Framework.Graphics.BlendFunction.ReverseSubtract;
                case BlendOperation.Subtract:
                    return Microsoft.Xna.Framework.Graphics.BlendFunction.Subtract;
            }
            throw new Exception("BlendOperation conversion error");
        }

        internal static BlendOperation convert(Microsoft.Xna.Framework.Graphics.BlendFunction op)
        {
            switch (op)
            {
                case Microsoft.Xna.Framework.Graphics.BlendFunction.Add:
                    return BlendOperation.Add;
                case Microsoft.Xna.Framework.Graphics.BlendFunction.Max:
                    return BlendOperation.Maximum;
                case Microsoft.Xna.Framework.Graphics.BlendFunction.Min:
                    return BlendOperation.Minimum;
                case Microsoft.Xna.Framework.Graphics.BlendFunction.ReverseSubtract:
                    return BlendOperation.ReverseSubtract;
                case Microsoft.Xna.Framework.Graphics.BlendFunction.Subtract:
                    return BlendOperation.Subtract;
            }
            throw new Exception("Blend function conversion error");
        }

        internal static Microsoft.Xna.Framework.Graphics.Blend convert(BlendOption opt)
        {
            switch (opt)
            {
                case BlendOption.BlendFactor:
                    return Microsoft.Xna.Framework.Graphics.Blend.BlendFactor;
                case BlendOption.DestinationAlpha:
                    return Microsoft.Xna.Framework.Graphics.Blend.DestinationAlpha;
                case BlendOption.DestinationColor:
                    return Microsoft.Xna.Framework.Graphics.Blend.DestinationColor;
                case BlendOption.InverseBlendFactor:
                    return Microsoft.Xna.Framework.Graphics.Blend.InverseBlendFactor;
                case BlendOption.InverseDestinationAlpha:
                    return Microsoft.Xna.Framework.Graphics.Blend.InverseDestinationAlpha;
                case BlendOption.InverseDestinationColor:
                    return Microsoft.Xna.Framework.Graphics.Blend.InverseDestinationColor;
                case BlendOption.InverseSourceAlpha:
                    return Microsoft.Xna.Framework.Graphics.Blend.InverseSourceAlpha;
                case BlendOption.InverseSourceColor:
                    return Microsoft.Xna.Framework.Graphics.Blend.InverseSourceColor;
                case BlendOption.One:
                    return Microsoft.Xna.Framework.Graphics.Blend.One;
                case BlendOption.SourceAlpha:
                    return Microsoft.Xna.Framework.Graphics.Blend.SourceAlpha;
                case BlendOption.SourceAlphaSaturate:
                    return Microsoft.Xna.Framework.Graphics.Blend.SourceAlphaSaturation;
                case BlendOption.SourceColor:
                    return Microsoft.Xna.Framework.Graphics.Blend.SourceColor;
                case BlendOption.Zero:
                    return Microsoft.Xna.Framework.Graphics.Blend.Zero;

                // I don't know how these correspond, so just fall through to throwing an exception
                case BlendOption.InverseSecondarySourceAlpha:
                case BlendOption.InverseSecondarySourceColor:
                case BlendOption.SecondarySourceAlpha:
                case BlendOption.SecondarySourceColor:
                    break;
            }
            throw new Exception("Blend option conversion error");
        }

        internal static BlendOption convert(Microsoft.Xna.Framework.Graphics.Blend opt)
        {
            switch (opt)
            {
                case Microsoft.Xna.Framework.Graphics.Blend.BlendFactor:
                    return BlendOption.BlendFactor;
                case Microsoft.Xna.Framework.Graphics.Blend.DestinationAlpha:
                    return BlendOption.DestinationAlpha;
                case Microsoft.Xna.Framework.Graphics.Blend.DestinationColor:
                    return BlendOption.DestinationColor;
                case Microsoft.Xna.Framework.Graphics.Blend.InverseBlendFactor:
                    return BlendOption.InverseBlendFactor;
                case Microsoft.Xna.Framework.Graphics.Blend.InverseDestinationAlpha:
                    return BlendOption.InverseDestinationAlpha;
                case Microsoft.Xna.Framework.Graphics.Blend.InverseDestinationColor:
                    return BlendOption.InverseDestinationColor;
                case Microsoft.Xna.Framework.Graphics.Blend.InverseSourceAlpha:
                    return BlendOption.InverseSourceAlpha;
                case Microsoft.Xna.Framework.Graphics.Blend.InverseSourceColor:
                    return BlendOption.InverseSourceColor;
                case Microsoft.Xna.Framework.Graphics.Blend.One:
                    return BlendOption.One;
                case Microsoft.Xna.Framework.Graphics.Blend.SourceAlpha:
                    return BlendOption.SourceAlpha;
                case Microsoft.Xna.Framework.Graphics.Blend.SourceAlphaSaturation:
                    return BlendOption.SourceAlphaSaturate;
                case Microsoft.Xna.Framework.Graphics.Blend.SourceColor:
                    return BlendOption.SourceColor;
                case Microsoft.Xna.Framework.Graphics.Blend.Zero:
                    return BlendOption.Zero;

                // Unknown - fall through to throw an exception
                //case Microsoft.Xna.Framework.Graphics.Blend.BothInverseSourceAlpha:
                //case Microsoft.Xna.Framework.Graphics.Blend.BothSourceAlpha:
                //case Microsoft.Xna.Framework.Graphics.Blend.InverseSourceAlpha:

            }
            throw new Exception("Blend selection conversion error");
        }

        internal static Microsoft.Xna.Framework.Graphics.ColorWriteChannels convert(ColorWriteMaskFlags flags)
        {
            Microsoft.Xna.Framework.Graphics.ColorWriteChannels res = 0;
            if ((flags & ColorWriteMaskFlags.Red) != 0)
                res |= Microsoft.Xna.Framework.Graphics.ColorWriteChannels.Red;
            if ((flags & ColorWriteMaskFlags.Blue) != 0)
                res |= Microsoft.Xna.Framework.Graphics.ColorWriteChannels.Blue;
            if ((flags & ColorWriteMaskFlags.Green) != 0)
                res |= Microsoft.Xna.Framework.Graphics.ColorWriteChannels.Green;
            if ((flags & ColorWriteMaskFlags.Alpha) != 0)
                res |= Microsoft.Xna.Framework.Graphics.ColorWriteChannels.Alpha;
            return res;
        }

        internal static ColorWriteMaskFlags convert(Microsoft.Xna.Framework.Graphics.ColorWriteChannels flags)
        {
            ColorWriteMaskFlags res = 0;
            if ((flags & Microsoft.Xna.Framework.Graphics.ColorWriteChannels.Red) != 0)
                res |= ColorWriteMaskFlags.Red;
            if ((flags & Microsoft.Xna.Framework.Graphics.ColorWriteChannels.Blue) != 0)
                res |= ColorWriteMaskFlags.Blue;
            if ((flags & Microsoft.Xna.Framework.Graphics.ColorWriteChannels.Green) != 0)
                res |= ColorWriteMaskFlags.Green;
            if ((flags & Microsoft.Xna.Framework.Graphics.ColorWriteChannels.Alpha) != 0)
                res |= ColorWriteMaskFlags.Alpha;
            return res;
        }

        internal static Microsoft.Xna.Framework.Color convert(Color4 c4)
        {
            return new Microsoft.Xna.Framework.Color(
                new Microsoft.Xna.Framework.Vector4(c4.Red, c4.Green, c4.Blue, c4.Alpha));
        }

        internal static Color4 convert(Microsoft.Xna.Framework.Color col)
        {
            Microsoft.Xna.Framework.Vector4 colv = col.ToVector4();
            return new Color4(new Vector4(colv.Z, colv.Y, colv.X, colv.W));
        }

        internal static Microsoft.Xna.Framework.Graphics.StencilOperation convert(StencilOperation op)
        {
            switch (op)
            {
                case StencilOperation.Decrement:
                    return Microsoft.Xna.Framework.Graphics.StencilOperation.Decrement;
                case StencilOperation.DecrementAndClamp:
                    return Microsoft.Xna.Framework.Graphics.StencilOperation.DecrementSaturation;
                case StencilOperation.Increment:
                    return Microsoft.Xna.Framework.Graphics.StencilOperation.Increment;
                case StencilOperation.IncrementAndClamp:
                    return Microsoft.Xna.Framework.Graphics.StencilOperation.IncrementSaturation;
                case StencilOperation.Invert:
                    return Microsoft.Xna.Framework.Graphics.StencilOperation.Invert;
                case StencilOperation.Keep:
                    return Microsoft.Xna.Framework.Graphics.StencilOperation.Keep;
                case StencilOperation.Replace:
                    return Microsoft.Xna.Framework.Graphics.StencilOperation.Replace;
                case StencilOperation.Zero:
                    return Microsoft.Xna.Framework.Graphics.StencilOperation.Zero;
            }
            throw new Exception("Stencil operation conversion error");
        }

        internal static StencilOperation convert(Microsoft.Xna.Framework.Graphics.StencilOperation op)
        {
            switch (op)
            {
                case Microsoft.Xna.Framework.Graphics.StencilOperation.Decrement:
                    return StencilOperation.Decrement;
                case Microsoft.Xna.Framework.Graphics.StencilOperation.DecrementSaturation:
                    return StencilOperation.DecrementAndClamp;
                case Microsoft.Xna.Framework.Graphics.StencilOperation.Increment:
                    return StencilOperation.Increment;
                case Microsoft.Xna.Framework.Graphics.StencilOperation.IncrementSaturation:
                    return StencilOperation.IncrementAndClamp;
                case Microsoft.Xna.Framework.Graphics.StencilOperation.Invert:
                    return StencilOperation.Invert;
                case Microsoft.Xna.Framework.Graphics.StencilOperation.Keep:
                    return StencilOperation.Keep;
                case Microsoft.Xna.Framework.Graphics.StencilOperation.Replace:
                    return StencilOperation.Replace;
                case Microsoft.Xna.Framework.Graphics.StencilOperation.Zero:
                    return StencilOperation.Zero;
            }
            throw new Exception("Stencil operation convertion error");
        }

        internal static Microsoft.Xna.Framework.Graphics.CompareFunction convert(Comparison comp)
        {
            switch (comp)
            {
                case Comparison.Always:
                    return Microsoft.Xna.Framework.Graphics.CompareFunction.Always;
                case Comparison.Equal:
                    return Microsoft.Xna.Framework.Graphics.CompareFunction.Equal;
                case Comparison.Greater:
                    return Microsoft.Xna.Framework.Graphics.CompareFunction.Greater;
                case Comparison.GreaterEqual:
                    return Microsoft.Xna.Framework.Graphics.CompareFunction.GreaterEqual;
                case Comparison.Less:
                    return Microsoft.Xna.Framework.Graphics.CompareFunction.Less;
                case Comparison.LessEqual:
                    return Microsoft.Xna.Framework.Graphics.CompareFunction.LessEqual;
                case Comparison.Never:
                    return Microsoft.Xna.Framework.Graphics.CompareFunction.Never;
                case Comparison.NotEqual:
                    return Microsoft.Xna.Framework.Graphics.CompareFunction.NotEqual;
            }
            throw new Exception("Error in comparison conversion");
        }

        internal static Comparison convert(Microsoft.Xna.Framework.Graphics.CompareFunction comp)
        {
            switch (comp)
            {
                case Microsoft.Xna.Framework.Graphics.CompareFunction.Always:
                    return Comparison.Always;
                case Microsoft.Xna.Framework.Graphics.CompareFunction.Equal:
                    return Comparison.Equal;
                case Microsoft.Xna.Framework.Graphics.CompareFunction.Greater:
                    return Comparison.Greater;
                case Microsoft.Xna.Framework.Graphics.CompareFunction.GreaterEqual:
                    return Comparison.GreaterEqual;
                case Microsoft.Xna.Framework.Graphics.CompareFunction.Less:
                    return Comparison.Less;
                case Microsoft.Xna.Framework.Graphics.CompareFunction.LessEqual:
                    return Comparison.LessEqual;
                case Microsoft.Xna.Framework.Graphics.CompareFunction.Never:
                    return Comparison.Never;
                case Microsoft.Xna.Framework.Graphics.CompareFunction.NotEqual:
                    return Comparison.NotEqual;
            }
            throw new Exception("Error in CompareFunction conversion");
        }

        internal static Microsoft.Xna.Framework.Graphics.FillMode convert(FillMode fmode)
        {
            switch (fmode)
            {
                case SlimDX.Direct3D11.FillMode.Solid:
                    return Microsoft.Xna.Framework.Graphics.FillMode.Solid;
                case SlimDX.Direct3D11.FillMode.Wireframe:
                    return Microsoft.Xna.Framework.Graphics.FillMode.WireFrame;
            }
            throw new Exception("Error in FillMode conversion");
        }

        internal static FillMode convert(Microsoft.Xna.Framework.Graphics.FillMode fmode)
        {
            switch (fmode)
            {
                case Microsoft.Xna.Framework.Graphics.FillMode.Solid:
                    return SlimDX.Direct3D11.FillMode.Solid;
                case Microsoft.Xna.Framework.Graphics.FillMode.WireFrame:
                    return SlimDX.Direct3D11.FillMode.Wireframe;
            }
            throw new Exception("Error in FillMode conversion");
        }

        internal static CullMode convert(Microsoft.Xna.Framework.Graphics.CullMode cmode)
        {
            // NOTE: Interpretation of back/front depends on IsFrontCounterclockwise setting
            //       Could cause confusion later, but atm there is no way of altering that
            //       setting in XNA - so all should be well unless it is changed in an effect
            switch (cmode)
            {
                case Microsoft.Xna.Framework.Graphics.CullMode.CullClockwiseFace:
                    return SlimDX.Direct3D11.CullMode.Front;
                case Microsoft.Xna.Framework.Graphics.CullMode.CullCounterClockwiseFace:
                    return SlimDX.Direct3D11.CullMode.Back;
                case Microsoft.Xna.Framework.Graphics.CullMode.None:
                    return SlimDX.Direct3D11.CullMode.None;
            }
            throw new Exception("Error in CullMode conversion");
        }

        internal static Microsoft.Xna.Framework.Graphics.CullMode convert(SlimDX.Direct3D11.CullMode cmode)
        {
            switch (cmode)
            {
                case SlimDX.Direct3D11.CullMode.Front:
                    return Microsoft.Xna.Framework.Graphics.CullMode.CullClockwiseFace;
                case SlimDX.Direct3D11.CullMode.Back:
                    return Microsoft.Xna.Framework.Graphics.CullMode.CullCounterClockwiseFace;
                case SlimDX.Direct3D11.CullMode.None:
                    return Microsoft.Xna.Framework.Graphics.CullMode.None;
            }
            throw new Exception("Error in CullMode conversion");
        }
    }
}
